<template>
  <div>
    <div v-if="initFieldsLoading">
      <div style="height: 100vh; width: 100vw" v-loading.lock="initFieldsLoading" element-loading-text="发布页面生成中..."></div>
    </div>
    <div v-else-if="!publishTypeDialog">
      <div class="content-publish-box" v-loading="submitLoading" element-loading-text="内容发布中...">
        <div class="publish-header">
          <div class="header-info">
            <span>{{ editId ? '修改' : '发布' }}{{ modelObj ? modelObj.name : '' }}（{{ categoryDetail.name }}）</span>
          </div>
          <div class="header-btn-box">
            <div class="btn-operate">
              <button v-if="!editId || fieldsValue.state == 1" class="header-btn" @click="submitAddPublish(formRef)">
                <i class="iconfont">&#xe6f0;</i>
                <span>发布</span>
              </button>
              <button class="header-btn" @click="submitDraft(formRef)">
                <i class="iconfont">&#xe6d2;</i>
                <span>保存</span>
              </button>
              <button class="header-btn" @click.stop="handlePreview">
                <i class="iconfont">&#xe6ee;</i>
                <span>预览</span>
              </button>
            </div>
            <div class="btn-quit">
              <div class="btn-operate">
                <button class="header-btn" @click="quitPublish">
                  <i class="iconfont">&#xe882;</i>
                  <span>退出</span>
                </button>
              </div>
            </div>
          </div>
        </div>
        <el-form id="tinymce-box" label-position="left" :model="fieldsValue" ref="formRef" :rules="formRules">
          <div class="publish-content">
            <div class="toolbar"></div>
            <!-- 资源展开 -->
            <div class="publish-left-content" v-show="fieldsList.editor_class && fieldsList.editor_class.fields.length > 0">
              <PublishResource :disabled="banResource" @handleUse="insertContent" />
            </div>
            <!-- 内容 -->
            <div class="publish-center-content">
              <el-scrollbar @scroll="handleCenterContentScroll">
                <div class="inner-publish-content">
                  <div class="editor-title" v-if="fieldsList.basic_msg.fields?.length > 0">
                    <div class="basic-content-item" v-for="item in fieldsList.basic_msg.fields" :key="item.id">
                      <RuifoxTitleBasic
                        v-if="item.component === 'title'"
                        :title="item.name"
                        v-model:value="fieldsValue[item['field']]"
                        :children="item.children"
                        v-model:childrenShow="item.childrenShow"
                        v-model:fieldsValue="fieldsValue"
                        :modelId="modelId"
                        :editId="editId"
                        :field="item.field"
                        :placeholder="item.tips"
                        :setting="item.setting"
                        @importArticle="handleImportMsg"
                      />
                      <el-collapse-transition>
                        <div v-show="item.children?.length > 0 && item.childrenShow">
                          <div v-for="child in item.children" :key="child.id">
                            <component
                              v-if="child.component !== 'image'"
                              :is="getControl(child)"
                              v-model:value="fieldsValue[child['field']]"
                              v-model:childrenShow="item.childrenShow"
                              :title="child.name"
                              :placeholder="child.tips"
                              :modelId="modelId"
                              :editId="editId"
                              :field="child.field"
                              :setting="child.setting"
                            />
                          </div>
                        </div>
                      </el-collapse-transition>
                    </div>
                  </div>
                  <div class="editor-box" v-loading="pasteLoading" element-loading-text="粘贴内容处理中...">
                    <div class="content-publish" v-show="!isLinkEditor">
                      <div class="page-footer-icon page-left-top"></div>
                      <div class="page-footer-icon page-right-top"></div>
                      <div>
                        <el-form-item :prop="fieldsList.editor_class.fields[0]?.field"></el-form-item>
                      </div>
                      <Editor
                        v-if="isPasting"
                        :id="fieldsList.editor_class.fields[0]?.field"
                        class="myedit"
                        v-model="fieldsValue[fieldsList.editor_class.fields[0]?.field]"
                        @blur="handleValidateField(fieldsList.editor_class.fields[0]?.field)"
                        :init="init"
                        tag-name="div"
                      />
                      <div class="page-footer-icon page-left-bottom"></div>
                      <div class="page-footer-icon page-right-bottom"></div>
                      <div id="img-btn-box" v-show="showImgOption" @mouseenter="showImgOption = true" @mouseleave="showImgOption = false">
                        <a href="javascript:;" @click="handleImgEditor('single')">编辑</a>
                      </div>
                    </div>
                    <div class="link-publish" v-show="isLinkEditor">
                      <div class="link-addr-input">
                        <el-form-item label="链接地址" prop="content">
                          <el-input class="input-link" disabled size="large" placeholder="请添加链接、附件或选择栏目内容" v-model="fieldsValue.content"></el-input>
                        </el-form-item>
                      </div>
                      <div class="link-addr-btn">
                        <el-button type="primary" @click="handleFillLink()">链接</el-button>
                        <el-button type="primary" @click="handleFillCategory()">栏目</el-button>
                        <el-button type="primary" @click="handleFillContent()">内容</el-button>
                      </div>
                    </div>
                  </div>
                  <div class="editor-right-btns-box" :style="{ top: editorBtnTop + 'px' }" :class="{ active: true }">
                    <div class="editor-right-btns">
                      <!-- <el-tooltip v-if="!isLinkEditor" class="box-item" effect="dark" content="从word导入" placement="right">
                        <div class="circle" @click="handleImportWord" v-if="fieldsList.editor_class.fields && fieldsList.editor_class.fields.length > 0">
                          <i class="iconfont">&#xe6f5;</i>
                        </div>
                      </el-tooltip> -->
                      <!-- <el-tooltip v-if="!isLinkEditor" class="box-item" effect="dark" content="从网址采集" placement="right">
                        <div class="circle" @click="handleCollect">
                          <i class="iconfont">&#xe6f6;</i>
                        </div>
                      </el-tooltip> -->
                      <el-popover placement="right" :width="80" trigger="hover" class="box-item" popper-class="style-popover">
                        <template #reference>
                          <div class="circle" @click="handleLayout('default')">
                            <i class="iconfont">&#xe6f7;</i>
                          </div>
                        </template>
                        <div class="style-choose">
                          <el-button link size="small" style="color: #fff" @click="handleLayout('default')">默认排版</el-button>
                          <el-button link size="small" style="color: #fff; margin: 6px 0 0" @click="handleLayout('more')">更多排版</el-button>
                        </div>
                      </el-popover>
                      <el-tooltip class="box-item" effect="dark" content="安全扫描" placement="right">
                        <div class="circle" @click="handleSafeScan()">
                          <i class="iconfont">&#xe6f8;</i>
                        </div>
                      </el-tooltip>
                    </div>
                  </div>
                </div>
              </el-scrollbar>
            </div>
            <!-- 拓展 -->
            <div class="publish-expand" :class="{ 'col-expand': expandState }">
              <div class="col-btn" @click="toggleExpand">
                <i class="iconfont">&#xe645;</i>
              </div>
              <div class="inner-expand-content">
                <el-tabs v-model="activeExpand">
                  <el-tab-pane label="发布设置" name="basicsAttr">
                    <template #label>
                      <el-tooltip effect="dark" content="发布设置" placement="top">
                        <span class="expand-tabs-label">
                          <i class="iconfont">&#xe78b;</i>
                        </span>
                      </el-tooltip>
                    </template>
                    <div class="basic-attribute">
                      <el-scrollbar style="width: 100%;">
                        <PublishSetting :data="fieldsList.publish_setting.fields" v-model:fieldsValue="fieldsValue" :editId="editId" :modelId="modelId" />
                      </el-scrollbar>
                    </div>
                  </el-tab-pane>
                  <el-tab-pane label="安全扫描" name="safeScan">
                    <template #label>
                      <el-tooltip effect="dark" content="安全扫描" placement="top">
                        <span class="expand-tabs-label">
                          <i class="iconfont">&#xe6f8;</i>
                        </span>
                      </el-tooltip>
                    </template>
                    <SafeScan
                      ref="safeScan"
                      :fieldsValue="fieldsValue"
                      :fieldsMapping="userFieldsMapping"
                      :fieldsFlat="userFieldsFlat"
                      :editor="tinymce"
                      @handleDeleteMark="handleDeleteMark"
                      @handleSetSafeDrawer="handleSetSafeDrawer"
                      @handleIgnore="handleIgnore"
                    ></SafeScan>
                  </el-tab-pane>
                  <!-- <el-tab-pane label="投递设置" name="deliver">
                    <template #label>
                      <el-tooltip effect="dark" content="投递设置" placement="top">
                        <span class="expand-tabs-label">
                          <i class="iconfont">&#xe6d8;</i>
                        </span>
                      </el-tooltip>
                    </template>
                    <Deliver />
                  </el-tab-pane> -->
                </el-tabs>
              </div>
            </div>
          </div>
          <ImageUpload v-if="showAxupImgs" v-model:showDialog="showAxupImgs" :limit="20" @getImage="insertImage" :isToJpg="true" allow=".jpg,.jpeg,.gif,.bmp,.png,.ico"></ImageUpload>
          <VideoUpload v-model:showDialog="showVideoUpload" @getVideo="insertVideo"></VideoUpload>
          <FilesUpload v-model:showDialog="showFilesUpload" @getFileList="insertFiles" :isToJpg="true"></FilesUpload>
        </el-form>
        <!-- 图片编辑 -->
        <PictureEdit
          v-if="showImgEditor"
          v-model:show="showImgEditor"
          :imgEditorList="imgEditorList"
          :editorImages="editorImages"
          :currentImg="currentImg"
          :isSingleEdit="isSingleEdit"
          :tinymce="tinymce"
        />
        <!-- 转向链接填写 -->
        <el-dialog v-model="showLinkFill" title="链接填写" width="600px">
          <div class="inner-collect">
            <p class="collect-title">请输入要链接的地址:</p>
            <el-input v-model="linkFill" size="large"></el-input>
          </div>
          <template #footer>
            <span class="dialog-footer">
              <div class="right-btn">
                <el-button type="primary" @click="submitFillLink">确认</el-button>
                <el-button @click="showLinkFill = false">关闭</el-button>
              </div>
            </span>
          </template>
        </el-dialog>
        <!-- 链接栏目 -->
        <DialogTree v-model:showDialog="showCategoryFill" :categoryList="fillCategoryList" :isSingle="true" @treeChoose="submitFillCategory"></DialogTree>
        <!-- 链接内容 -->
        <ContentLinks v-model:showLinkTabs="showContentFill" @handleLink="submitFillContent" />
        <!-- 一键排版 -->
        <AutoStyle v-model:show="showAutoStyle" :formatList="formatList" :instance="tinymce" :fieldsValue="fieldsValue" @updateList="handleGetFormatList" />
        <!-- 网络采集 -->
        <el-dialog v-model="showCollect" title="网络采集" width="600px">
          <div class="inner-collect">
            <p class="collect-title">请输入要采集的文章地址:</p>
            <el-input v-model="collectParams.targetUrl" size="large" style="margin-bottom: 20px"></el-input>
            <p class="collect-title">目前支持的文章:</p>
            <div class="collect-tips">
              <p>微信公众号，微博文章，知乎专栏，网易新闻，百家号</p>
            </div>
            <el-button type="primary" style="width: 100%; margin-top: 15px" size="large" @click="submitCollect" :loading="collectLoading">采集</el-button>
          </div>
        </el-dialog>
        <!-- word导入 -->
        <el-dialog v-model="showImportWord" width="680px" title="Word导入" :close-on-click-modal="false" :close-on-press-escape="false">
          <div v-loading="importLoading" element-loading-text="内容导入中...">
            <el-upload
              class="options-item import-word"
              :show-file-list="false"
              :http-request="handleUpload"
              :on-exceed="handleExceed"
              v-model:file-list="wordUploadList"
              :limit="1"
              accept=".docx"
              drag
            >
              <el-icon class="el-icon--upload"><upload-filled /></el-icon>
              <div class="el-upload__text">
                将word文件拖动到此处上传 或者
                <em>点击这里</em>
                ,仅支持docx格式
              </div>
              <template #tip>
                <div class="el-upload__tip" style="margin-top: 10px; font-size: 14px">导入后编辑器将插入word中的内容，不支持的样式或图片可能无法展示，请确认后发布</div>
              </template>
            </el-upload>
          </div>
        </el-dialog>
      </div>
    </div>
    <el-dialog
      v-model="publishTypeDialog"
      class="publish-type-dialog"
      title="请选择发布方式"
      width="300px"
      center
      align-center
      :show-close="false"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
    >
      <div class="publish-type-box">
        <el-button @click="handlePublishType('link')">转载链接</el-button>
        <el-button type="primary" @click="handlePublishType('content')">发布原创</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script setup>
import Editor from '@tinymce/tinymce-vue'
import tinymce from 'tinymce/tinymce' //tinymce默认hidden，不引入则不显示编辑器
import axios from 'axios'
import { ref, onMounted, reactive, watch, nextTick, computed, markRaw } from 'vue'
import { UploadFilled } from '@element-plus/icons-vue'
import { useStore } from 'vuex'
import { useRouter } from 'vue-router'
import { importContent } from '@/api/content'
import { ElMessage, ElMessageBox } from 'element-plus'
/********java接口*************/
import { checkPreview, insertContent as contentInsert, getContentDetail, updateContent, insertDraft, insertContentByImport } from '@/api/content'
import { getCategoryDetail } from '@/api/category'
import { getModelDetail } from '@/api/model'
import { addCollectTask } from '@/api/collect'
import { getFormatList } from '@/api/layout-template'
import { createMapping, transBase64FromImage, myDebounce } from '@/utils/tools'
import { createTreeData } from '@ruifox-cms/utils'
import { getSiteGroup } from '@/utils/storage'
/******右侧拓展信息表单拆分******/
import PublishSetting from './components/PublishSetting'
import PublishResource from './components/PublishResource'
import AutoStyle from './components/AutoStyle'
import SafeScan from './components/SafeScan'
import PictureEdit from './components/PictureEdit'
// import Deliver from './components/Deliver'
/**********动态组件****************/
import RuifoxTextBasic from '@/components/ruifoxComponents/RuifoxTextBasic'
import RuifoxTextareaBasic from '@/components/ruifoxComponents/RuifoxTextareaBasic'
import RuifoxTitleBasic from '@/components/ruifoxComponents/RuifoxTitleBasic'
import RuifoxSelectBasic from '@/components/ruifoxComponents/RuifoxSelectBasic'
import RuifoxDepartBasic from '@/components/ruifoxComponents/RuifoxDepartBasic'
import RuifoxThumbBasic from '@/components/ruifoxComponents/RuifoxThumbBasic'
import RuifoxDateBasic from '@/components/ruifoxComponents/RuifoxDateBasic'
import RuifoxSelectMultipleBasic from '@/components/ruifoxComponents/RuifoxSelectMultipleBasic'
import RuifoxCheckboxBasic from '@/components/ruifoxComponents/RuifoxCheckboxBasic'
import RuifoxRadioBasic from '@/components/ruifoxComponents/RuifoxRadioBasic'
import RuifoxNumberBasic from '@/components/ruifoxComponents/RuifoxNumberBasic'
import { createTinyConfig } from './config/tinyConfig'

const store = useStore()
const router = useRouter()
const editId = ref(router.currentRoute.value.query.dataId ? router.currentRoute.value.query.dataId : '')
const catId = ref(Number(router.currentRoute.value.query.catId)) // 栏目id
const modelId = ref(router.currentRoute.value.query.modelId) // 模型id
const autoSaveKey = 'destroy_form_' + catId.value
const canAutoSave = ref(!localStorage.getItem(autoSaveKey))
const initFieldsLoading = ref(true) // 表单加载状态
const clip_port = ref(store.state.content.clip_port)
const submitLoading = ref(false) // 发布操作loading
const pluginConfig = computed(() => store.state.content.pluginConfig)
const isPasting = ref(true)
const pasteLoading = ref(false) // 粘贴中
/*************************************************************************页面初始化准备start***************************************************/
// 获取栏目详情
const categoryDetail = ref({})
const handleGetCategoryDetail = async () => {
  const res = await getCategoryDetail({ id: catId.value })
  if (res.code === 20000) {
    categoryDetail.value = res.data
  }
}
handleGetCategoryDetail()

// 获取模型详情
const modelObj = ref({})
const positionList = ref([])
const _getModelDetail = async () => {
  const res = await getModelDetail({ id: modelId.value })
  modelObj.value = res.data
  positionList.value = res.data.positions
}

// 表单字段字段处理
const userFields = ref([])
const userFieldsFlat = ref([])
const userFieldsMapping = ref({})
const fieldsValue = ref({}) // 用户填写表单
const fieldsList = ref({}) // 表单字段按位置划分处理
const formRules = ref([]) // 表单校验规则
const formRef = ref() // 表单ref
const getFields = async () => {
  initFieldsLoading.value = true
  let flatField = await store.dispatch('content/updateFieldList', modelId.value)
  if (flatField) {
    genFormRules(flatField)
    userFields.value = flatField.filter(item => item.isForm)
    userFieldsFlat.value = structuredClone(flatField)
    userFieldsMapping.value = createMapping(flatField, { keyProp: 'field', valueProp: 'name' })
    userFields.value = createTreeData(userFields.value, 'relyFieldId', 'children')
    // 字段信息格式整理
    positionList.value.forEach(item => {
      fieldsList.value[item.value] = {}
      fieldsList.value[item.value].fields = userFields.value.filter(field => field.setting.fieldPosition === item.value)
    })
  }
  initFieldsLoading.value = false
  // 检测如果有保存的内容且取消恢复内容，则显示发布模式选择弹窗。若确认恢复，需要根据数据情况加载对应的发布模式界面
  let destroyFormValue = localStorage.getItem(autoSaveKey) ? JSON.parse(localStorage.getItem(autoSaveKey)) : undefined
  if (destroyFormValue && destroyFormValue.modelId === modelId.value && destroyFormValue.catId === catId.value && !editId.value) {
    ElMessageBox.confirm('<div><p style="font-size: 14px;">您上次有编辑未保存的内容是否恢复内容</p></div>', '提示', {
      dangerouslyUseHTMLString: true,
      confirmButtonText: '确认',
      cancelButtonText: '取消'
    })
      .then(() => {
        if (destroyFormValue.form.is_link == 1) {
          isLinkEditor.value = true
        }
        Object.assign(fieldsValue.value, destroyFormValue.form)
        canAutoSave.value = true
      })
      .catch(() => {
        publishTypeDialog.value = true
        canAutoSave.value = true
        localStorage.removeItem(autoSaveKey)
      })
  } else {
    // 如果有内容id或草稿id，则不显示，根据内容判断显示哪个编辑页面
    if (!editId.value) {
      publishTypeDialog.value = true
      canAutoSave.value = true
    } else {
      if (fieldsValue.value.is_link == 1) {
        handlePublishType('link')
      }
    }
  }
}

// 表单以及验证规则生成
const genFormRules = fields => {
  fields.forEach(item => {
    if (item.isRequired) {
      formRules.value[item.field] = [
        {
          required: item.isRequired,
          message: `${item.name}不能为空`,
          trigger: 'change'
        }
      ]
    }
    if (item.isForm && item.defaultValue) {
      fieldsValue.value[item.field] = item.defaultValue
    }
  })
}

// 字段校验
const handleValidateField = field => {
  formRef.value.validateField(field)
}

// 获取排版格式
const formatList = ref([])
const defaultFormat = computed(() => {
  const defaultData = formatList.value.find(item => item.isDefault)
  return defaultData ? defaultData : formatList.value[0]
})
const handleGetFormatList = async () => {
  const res = await getFormatList()
  if (res.code === 20000) {
    formatList.value = res.data
  }
}
handleGetFormatList()

// 保存图片为base64
const setAvatarBase64 = (src, width, height) => {
  return new Promise(resolve => {
    let image = new Image()
    // 处理缓存
    image.src = src + '?v=' + Math.random()
    // 支持跨域图片
    image.crossOrigin = 'anonymous'
    if (width) image.width = width
    if (height) image.height = height
    image.onload = () => {
      let base64 = transBase64FromImage(image)
      resolve(base64)
    }
  })
}
/*************************************************************************页面初始化准备end***************************************************/

/*************************************************************************编辑器工具栏start***************************************************/
// 135编辑器
let editor135
const onContentFrom135 = event => {
  if (typeof event.data !== 'string') {
    if (event.data.ready) {
      editor135.postMessage(tinymce.activeEditor.getContent(), '*')
    }
    return
  }

  if (event.data.indexOf('<') !== 0) return

  tinymce.activeEditor.setContent(event.data)
  fieldsValue.value[tinymce.activeEditor.id] = tinymce.activeEditor.getContent()
  window.removeEventListener('message', onContentFrom135)
}

//图片编辑器
const imgEditorList = ref([])
const showImgEditor = ref(false)
const isSingleEdit = ref(false)
const editorImages = ref([]) //要编辑的图片列表
const currentImg = ref({}) // 当前正在编辑的图片
const curHoverImg = ref({}) // 当前正在编辑的图片
const showImgOption = ref(false)
const moduleClassName = ref('module-img') // 模板图片类名
const handleImgEditor = type => {
  isSingleEdit.value = type == 'single' ? true : false
  imgEditorList.value = []
  editorImages.value = []
  // 获取所有图片
  let tinyCnt = tinymce.activeEditor.getContent()
  let imgList = []
  if (tinyCnt) {
    imgList = tinymce.activeEditor.dom.select('img')
  }
  if (imgList && imgList.length > 0) {
    showImgEditor.value = true
    if (type != 'single') {
      imgList.forEach((item, index) => {
        let imgObj = {
          id: index,
          url: item.src,
          oldUrl: item.src,
          checked: true, //默认全部勾选
          isModuleImg: item.className == moduleClassName.value ? true : false, //是否是模板图片
          imgSize: {
            width: item.width,
            height: item.height
          },
          oldImgSize: {
            width: item.width,
            height: item.height
          }
        }
        imgEditorList.value.push(JSON.parse(JSON.stringify(imgObj)))
        editorImages.value.push(JSON.parse(JSON.stringify(imgObj)))
      })
    } else {
      //单个编辑
      let curHoverImgObj = {
        id: 0,
        url: curHoverImg.value.src,
        oldUrl: curHoverImg.value.src,
        checked: true,
        isModuleImg: curHoverImg.value.className == moduleClassName.value ? true : false, //是否是模板图片
        imgSize: {
          width: curHoverImg.value.width,
          height: curHoverImg.value.height
        },
        oldImgSize: {
          width: curHoverImg.value.width,
          height: curHoverImg.value.height
        }
      }
      imgEditorList.value = [curHoverImgObj]
      editorImages.value = [curHoverImgObj]
    }

    imgEditorList.value.forEach(item => {
      setAvatarBase64(item.url).then(base64 => {
        item.base64Url = base64
      })
    })
  } else {
    //提示没有图片
    ElMessage({
      message: '稿件内容中没有图片',
      type: 'warning'
    })
  }
}

// 一键排版
const showAutoStyle = ref(false)
const handleLayout = type => {
  if (type === 'more') {
    showAutoStyle.value = true
  } else {
    tinymce.activeEditor.plugins.layout.doAction(defaultFormat.value.rule)
    fieldsValue.value[tinymce.activeEditor.id].replace(/layoutFV/g, '')
    tinymce.activeEditor.dom.$('.layoutFV').removeClass('layoutFV')
  }
}

// 视频上传
const showVideoUpload = ref(false)
const insertVideo = videoList => {
  let videoContent = ``
  videoList.forEach(item => {
    let _video = `<p>
          <span class="mce-preview-object mce-object-video" contenteditable="false" data-mce-object="video" data-mce-p-allowfullscreen="allowfullscreen" data-mce-p-frameborder="no" data-mce-p-scrolling="no" data-mce-p-src=${item.url} data-mce-html="%20">
            <video width="100%" controls="controls" poster=${item.thumb}>
              <source src=${item.url}>
              你的浏览器不支持HTML5视频
            </video>
          </span>
        </p>`
    videoContent = videoContent + _video
  })
  tinymce.activeEditor.insertContent(videoContent + '<p></p>')
}

// 图片上传
const showAxupImgs = ref(false)
const insertImage = imgList => {
  let imgContent = ``
  imgList.forEach(item => {
    let _img = `<p><img src="${item.url}" origin-src="${item.oriUrl}" /></p>`
    imgContent = imgContent + _img
  })
  tinymce.activeEditor.insertContent(imgContent + '<p></p>')
}

// 附件上传
const showFilesUpload = ref(false)
const insertFiles = filesList => {
  let filesContent = ``
  filesList.forEach(item => {
    let _file = `<p><a href="${item.url}">${item.name}</a></p>`
    filesContent = filesContent + _file
  })
  tinymce.activeEditor.insertContent(filesContent + '<p></p>')
}

// 网络采集功能
const showCollect = ref(false)
const collectLoading = ref(false)
const collectParams = reactive({
  detailTemplateId: 1,
  pageNumber: 0,
  pageTemplateId: null,
  targetUrl: '',
  type: 0
})
// eslint-disable-next-line
const handleCollect = () => {
  collectParams.targetUrl = ''
  showCollect.value = true
}
const submitCollect = () => {
  collectLoading.value = true
  addCollectTask(collectParams)
    .then(res => {
      // 填充内容(处理双引号里面还有双引号问题)
      const content = res.data.content.replace(/url\("([^"]+)"\)/g, 'url($1)')
      tinymce.activeEditor.setContent(content)
      fieldsValue.value[tinymce.activeEditor.id] = content
      fieldsValue.value.title = res.data.title.match(/>([^<]+)/)[1]
      ElMessage({
        showClose: true,
        message: '采集成功',
        type: 'success'
      })
      collectLoading.value = false
      showCollect.value = false
    })
    .catch(() => {
      collectLoading.value = false
      showCollect.value = false
    })
}

// 插入样式或模板
const banResource = ref(false) // 禁用标志（发布链接的时候禁用）
const insertContent = (content, msg) => {
  tinymce.activeEditor.insertContent(content + '<p></p>')
  ElMessage({
    showClose: true,
    message: msg,
    type: 'success'
  })
}

// word导入功能
const showImportWord = ref(false)
const importLoading = ref(false)
const wordUploadList = ref([])
// eslint-disable-next-line
const handleImportWord = () => {
  showImportWord.value = true
  wordUploadList.value = []
}
const handleUpload = async option => {
  let formData = new FormData()
  importLoading.value = true
  formData.append('file', option.file)
  const checkPromise = (url, formData) => {
    return new Promise((resolve, reject) => {
      axios
        .post(url, formData, {
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        })
        .then(res => {
          if (res.data.code) resolve(res)
          else reject()
        })
        .catch(() => {
          reject()
        })
    })
  }
  const precheckUploadPort = () => {
    const importUrl = 'http://127.0.0.1:' + clip_port.value + '/upload'
    return checkPromise(importUrl, formData)
      .then(res => {
        try {
          const tempDiv = document.createElement('div')
          tempDiv.id = 'temp-content-div'
          tempDiv.style.display = 'none'
          document.body.appendChild(tempDiv)
          const did = document.getElementById('temp-content-div')
          did.innerHTML = res.data.data
          let styleTag = document.querySelector('#temp-content-div>style')
          let content = document.querySelector('#temp-content-div>div')
          if (content) content.style = ''
          else {
            content = document.querySelector('#temp-content-div>p')
          }
          // 获取 style 标签中的样式规则
          let styleSheet = styleTag.sheet
          let cssRules = styleSheet.cssRules || styleSheet.rules
          // 遍历每个样式规则
          Array.from(cssRules).forEach(cssRule => {
            let selectorText = cssRule.selectorText
            let style = cssRule.style
            // 获取匹配样式规则的元素
            let elements = content.querySelectorAll(selectorText)

            // 将样式应用到元素的行内样式
            Array.from(elements).forEach(element => {
              // 应用样式规则到元素的行内样式
              for (let i = 0; i < style.length; i++) {
                const propName = style[i]
                const propValue = style.getPropertyValue(propName)
                if (!element.style[propName]) element.style[propName] = propValue
              }
            })
          })
          // 移除 style 标签
          styleTag.parentNode.removeChild(styleTag)
          tinymce.activeEditor.insertContent(did.innerHTML)
          tinymce.activeEditor.uploadImages()
          did.remove()
          importLoading.value = false
          showImportWord.value = false
        } catch (error) {
          console.log('失败', error)
        }
      })
      .catch(() => {
        if (clip_port.value < 10089) {
          clip_port.value++
          precheckUploadPort()
        } else {
          importLoading.value = false
          showImportWord.value = false
          const foxClipLink = document.createElement('a')
          foxClipLink.href = 'foxc://'
          foxClipLink.target = '_self'
          foxClipLink.click()
          // 判断用户界面失焦
          let userOnblur = false
          window.onblur = function () {
            userOnblur = true
          }
          setTimeout(() => {
            if (!userOnblur) {
              ElMessageBox.confirm('<div><p style="font-size: 16px;margin-bottom: 15px;">下载粘贴导入工具，下载文件包内含安装步骤</p></div>', '下载确认', {
                distinguishCancelAndClose: true,
                dangerouslyUseHTMLString: true,
                confirmButtonText: '确认下载',
                cancelButtonText: '暂不安装（使用原始导入）'
              })
                .then(() => {
                  window.open(pluginConfig.value.downloadLink)
                })
                .catch(async action => {
                  if (action === 'cancel') {
                    let res = await insertContentByImport({ catId: catId.value, file: option.file })
                    showImportWord.value = false
                    tinymce.activeEditor.insertContent(res.data.content)
                  }
                })
            }
          }, 300)
        }
      })
  }
  precheckUploadPort()
}

const handleExceed = () => {
  ElMessage({
    showClose: true,
    message: '只允许上传一个word文件',
    type: 'warning'
  })
}
/*************************************************************************编辑器工具栏end***************************************************/

/*************************************************************************表单中心**********************************************************/
// 基本信息区的控件组件映射
const controlMapBasic = reactive({
  text: markRaw(RuifoxTextBasic),
  textarea: markRaw(RuifoxTextareaBasic),
  title: markRaw(RuifoxTitleBasic),
  select: markRaw(RuifoxSelectBasic),
  depart: markRaw(RuifoxDepartBasic),
  image: markRaw(RuifoxThumbBasic),
  datetime: markRaw(RuifoxDateBasic),
  selectMultiple: markRaw(RuifoxSelectMultipleBasic),
  checkbox: markRaw(RuifoxCheckboxBasic),
  radio: markRaw(RuifoxRadioBasic),
  number: markRaw(RuifoxNumberBasic)
})
const getControl = data => {
  return controlMapBasic[data.component]
}

// 导入发布（有相似文章时进行导入）
const handleImportMsg = val => {
  importContent({ model_id: modelId.value, id: val.id, cat_id: catId.value }).then(() => {
    // 告知页面刷新
    setTimeout(() => {
      submitLoading.value = false
      window.opener.updatePage('导入内容成功')
      window.close()
    }, 0)
  })
}

// 发布链接-自定义链接
const showLinkFill = ref(false)
const linkFill = ref('')
const handleFillLink = () => {
  linkFill.value = ''
  showLinkFill.value = true
}
const submitFillLink = () => {
  fieldsValue.value.content = linkFill.value
  showLinkFill.value = false
}

// 发布链接-栏目链接
const showCategoryFill = ref(false)
const fillCategoryList = ref()
const handleFillCategory = () => {
  let data = []
  data = getSiteGroup()?.map(item => {
    return {
      name: item.name,
      id: item.id
    }
  })
  data.forEach(item => {
    item.children = []
    store.state.category.categoryTree.forEach(item2 => {
      if (item2.siteId === item.id) {
        item.children.push(item2)
      }
    })
  })
  fillCategoryList.value = data
  showCategoryFill.value = true
}
const submitFillCategory = val => {
  const { domain, uri } = store.state.site.currentSite
  fieldsValue.value.content = domain + uri + val[0].uri
}

// 发布链接-内容链接
const showContentFill = ref(false)
const handleFillContent = () => {
  showContentFill.value = true
}
const submitFillContent = content => {
  fieldsValue.value.content = content.uri
  showContentFill.value = false
}

// 右侧拓展属性
const expandState = ref(true)
const activeExpand = ref('basicsAttr')
const toggleExpand = () => {
  expandState.value = !expandState.value
}

// 选择发布模式
const isLinkEditor = ref(false)
const publishTypeDialog = ref(false)
const handlePublishType = type => {
  publishTypeDialog.value = false
  if (type === 'link') {
    isLinkEditor.value = true
    banResource.value = true
    fieldsValue.value.is_link = 1
    nextTick(() => {
      const publishContent = document.querySelector('.publish-content')
      publishContent.style.paddingTop = '0'
      const innerPublishContent = document.querySelector('.inner-publish-content')
      innerPublishContent.style.marginTop = '120px'
    })
  } else {
    fieldsValue.value.is_link = 0
  }
}

// 获取内容详情
const _getContentDetail = async () => {
  const query = {
    catId: catId.value,
    dataId: editId.value
  }
  const res = await getContentDetail(query)
  if (res.code === 20000) {
    if (res.data.is_link == 1) {
      handlePublishType('link')
    }
    Object.assign(fieldsValue.value, res.data)
  }
}

// 自动保存内容(编辑模式不自动保存)
const _autoSaveContent = () => {
  if (!editId.value && canAutoSave.value) {
    localStorage.setItem(
      autoSaveKey,
      (() => {
        let val = {
          form: fieldsValue.value,
          modelId: modelId.value,
          catId: catId.value
        }
        return JSON.stringify(val)
      })()
    )
  }
}
const autoSaveContent = myDebounce(_autoSaveContent, 1500)
watch(
  () => fieldsValue.value,
  () => {
    autoSaveContent()
  },
  { deep: true }
)

// 安全扫描
const safeScan = ref(null)
const handleSafeScan = async (isPublish = false, showIgnore = false, showResult = true) => {
  const result = await safeScan.value.handleSafeScan(showIgnore, showResult)
  // 检验是否为发布按钮触发的安全扫描
  if (isPublish && result.isPass) {
    handleRelease()
  }
}

// 安全扫描-父组件抽屉展开
const handleSetSafeDrawer = () => {
  expandState.value = true
  activeExpand.value = 'safeScan'
}

// 安全扫描-忽略事件
const handleIgnore = () => {
  handleRelease()
}

// 安全扫描-删除标记
const handleDeleteMark = () => {
  // 循环编辑器删除标记
  fieldsList.value.editor_class.fields.forEach(item => {
    const $ = tinymce.editors[item.field].dom.$
    // 删除敏感词标记
    $("span[data-foxword='yes']").each(function () {
      $(this).replaceWith($(this).html())
    })
    // 删除外链标记
    $("a[data-foxword='yes']").each(function () {
      $(this).removeClass('scan-words').removeClass('links-span').removeAttr('data-id data-foxword')
    })
    fieldsValue.value[item.field] = tinymce.editors[item.field].getContent()
  })
}

// 表单发布
const submitAddPublish = async formEl => {
  if (!formEl) return
  await formEl.validate((valid, fields) => {
    if (valid) {
      if (!isLinkEditor.value) {
        handleSafeScan(true, true, false)
      } else {
        handleRelease()
      }
    } else {
      // 对每个未填写的字段分别弹出提示
      for (const field in fields) {
        const position = getFieldPosition(field)
        const fieldName = userFieldsMapping.value[field]
        ElMessage({
          showClose: true,
          message: `${position}-${fieldName}不能为空`,
          type: 'warning'
        })
      }
    }
  })
}

const getFieldPosition = field => {
  // 根据field在userFieldsFlat中找到对应的字段信息
  const fieldInfo = userFieldsFlat.value.find(f => f.field === field)
  if (fieldInfo) {
    // 从positionList中获取位置名称
    const position = positionList.value.find(p => p.value === fieldInfo.setting.fieldPosition)
    return position ? position.label : ''
  }
  return ''
}

// 表单提交
const handleRelease = async () => {
  autoGrabThumb()
  const formData = {}
  formData.catId = catId.value
  formData.dataContent = fieldsValue.value
  delete formData.dataContent.cat_id
  try {
    submitLoading.value = true
    let res
    if (fieldsValue.value.id) {
      formData.id = fieldsValue.value.id
      res = await updateContent(formData)
    } else {
      res = await contentInsert(formData)
    }
    submitLoading.value = false
    if (res.code === 20000) {
      ElMessage.success(fieldsValue.value.id ? '修改成功' : '发布成功')
      // 告知页面刷新
      setTimeout(() => {
        window.opener.updatePage(fieldsValue.value.id ? '修改成功' : '发布成功')
        window.close()
      }, 0)
    }
  } catch (e) {
    submitLoading.value = false
  }
}

// 表单保存（如果有id，则更新，否则添加到草稿箱）
const submitDraft = async formEl => {
  if (!formEl) return
  formEl.validateField('title', async valid => {
    if (valid) {
      submitLoading.value = true
      autoGrabThumb()
      const formData = {}
      formData.catId = catId.value
      formData.dataContent = fieldsValue.value
      delete formData.dataContent.cat_id
      let res, msg
      if (fieldsValue.value.id) {
        formData.id = fieldsValue.value.id
        msg = '修改成功'
        res = await updateContent(formData)
      } else {
        msg = '保存草稿成功'
        res = await insertDraft(formData)
      }
      if (res.code === 20000) {
        submitLoading.value = false
        window.opener.updatePage(msg)
        window.close()
      }
    } else {
      ElMessage({
        showClose: true,
        message: '标题不能为空',
        type: 'warning'
      })
    }
  })
}

// 缩略图自动抓取
const autoGrabThumb = () => {
  if (!fieldsValue.value.thumb) {
    const thumbField = userFieldsFlat.value.find(item => item.field === 'thumb')
    if (thumbField) {
      const grabField = thumbField.setting.grabfield
      if (grabField) {
        const grabFieldValue = fieldsValue.value[grabField]
        const imgMatch = grabFieldValue.match(/<img[^>]+src=["']([^"']+)["'][^>]*>/i)
        if (imgMatch && imgMatch[1]) {
          fieldsValue.value.thumb = imgMatch[1]
        }
      }
    }
  }
}

// 预览
const handlePreview = () => {
  if (isLinkEditor.value) {
    if (!fieldsValue.value.content) {
      ElMessage({
        showClose: true,
        message: '请填写链接地址！',
        type: 'error'
      })
    } else {
      window.open(fieldsValue.value.content, '_blank')
    }
  } else {
    formRef.value.validateField('title', valid => {
      if (!valid) {
        ElMessage({
          showClose: true,
          message: '请填写标题！',
          type: 'error'
        })
        return
      }
      if (categoryDetail.value.detailTemplate) {
        checkPreview({
          catId: catId.value,
          dataContent: fieldsValue.value
        }).then(res => {
          const htmlContent = res.data
          const blob = new Blob([htmlContent], { type: 'text/html' })
          const url = URL.createObjectURL(blob)
          let toUrl = router.resolve({
            path: '/content/manage/preview',
            query: { url }
          })
          window.open(toUrl.href, '_blank')
        })
      } else {
        ElMessage({
          showClose: true,
          message: '该栏目未选择详情模板！',
          type: 'error'
        })
      }
    })
  }
}

// 退出
const quitPublish = () => {
  ElMessageBox.confirm('<div><p style="font-size: 16px;margin-bottom: 15px;">内容尚未发布是否立即退出？</p></div>', '退出确认', {
    dangerouslyUseHTMLString: true,
    confirmButtonText: '确认',
    cancelButtonText: '取消'
  }).then(() => {
    // 告知页面刷新
    setTimeout(() => {
      window.close()
    }, 0)
  })
}

// 工具条上边距控制
const editorBtnTop = ref(0)
const handleCenterContentScroll = val => {
  editorBtnTop.value = val.scrollTop
}

const init = reactive(
  createTinyConfig({
    pasteLoading,
    editor135,
    showImgOption,
    currentImg,
    curHoverImg,
    showAxupImgs,
    showVideoUpload,
    showFilesUpload,
    isPasting,
    handlers: {
      handleImgEditor,
      setAvatarBase64,
      onContentFrom135
    }
  })
)
/****************其他功能******************/

// 初始化
onMounted(async () => {
  await _getModelDetail()
  await getFields()
  if (editId.value) {
    await _getContentDetail()
  }
})

window.addEventListener('beforeunload',() => {
  // 销毁发布
  if (tinymce.activeEditor)
    tinymce.activeEditor.destroy()
  // 正常关闭删除自动保存的内容
  localStorage.removeItem(autoSaveKey)
})
</script>

<style scoped lang="scss">
.content-publish-box {
  width: 100vw;
  .publish-header {
    height: 64px;
    background-color: $mainColor;
    display: flex;
    padding: 0 16px;
    justify-content: space-between;
    align-items: center;
    .header-info {
      display: flex;
      color: $white;
      align-items: center;
      span {
        font-size: 14px;
      }
    }
    .header-btn-box {
      display: flex;
      align-items: center;
      .btn-quit {
        margin-left: 40px;
      }
      .btn-operate {
        display: flex;
        align-items: center;
        .header-btn + .header-btn {
          margin-left: 10px;
        }
      }
      .header-btn {
        padding: 0 15px;
        border: none;
        border-radius: 4px;
        background-color: rgba(#fff, 0.2);
        color: #fff;
        transition: all 0.25s;
        font-size: 14px;
        display: flex;
        align-items: center;
        height: 32px;
        cursor: pointer;
        &:hover {
          color: $mainColor;
          background-color: #fff;
        }
        i {
          font-size: 14px;
          margin-right: 4px;
        }
      }
    }
  }
  .publish-content {
    position: relative;
    display: flex;
    height: calc(100vh - 64px);
    box-sizing: border-box;
    padding-top: 126px;
    background-color: $focusContent;
    overflow: hidden;
    .publish-left-content {
      height: 100%;
    }
    .publish-center-content {
      flex: 1;
      height: 100%;
      .inner-publish-content {
        position: relative;
        width: 880px;
        margin: 20px auto 20px;
        background-color: #ffffff;
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
        box-sizing: border-box;
        padding: 0 40px 40px;
        .editor-title {
          min-height: 40px;
        }
        .editor-box {
          ::v-deep(.el-form-item__error) {
            top: -14px;
            left: 10px;
          }
          ::v-deep(.el-form-item) {
            margin: 0;
          }
          .content-publish {
            position: relative;
            min-height: calc(765px - 107px - 40px - 21px);
            margin-top: 21px;
            .page-footer-icon {
              height: 20px;
              width: 20px;
              position: absolute;
            }
            .page-left-top {
              left: -21px;
              top: -21px;
              border-right: 1px solid $weightBar;
              border-bottom: 1px solid $weightBar;
            }
            .page-right-top {
              right: -21px;
              top: -21px;
              border-left: 1px solid $weightBar;
              border-bottom: 1px solid $weightBar;
            }
            .page-left-bottom {
              left: -21px;
              bottom: -21px;
              border-right: 1px solid $weightBar;
              border-top: 1px solid $weightBar;
            }
            .page-right-bottom {
              right: -21px;
              bottom: -21px;
              border-left: 1px solid $weightBar;
              border-top: 1px solid $weightBar;
            }
            .myedit {
              outline: none;
              overflow: hidden;
              min-height: calc(100vh - 454px);
            }
          }
          .link-publish {
            display: flex;
            align-items: center;
            margin-top: 30px;
            .link-addr-input {
              flex: 1;
              margin-right: 10px;
              ::v-deep(.el-form-item) {
                margin-bottom: 0;
                align-items: center;
              }
            }
          }
          #img-btn-box {
            position: absolute;
            top: 0;
            left: 0;
            a {
              text-align: center;
              height: 20px;
              font-size: 12px;
              line-height: 20px;
              background-color: $mainColor;
              border-radius: 4px;
              color: #fff;
              box-shadow: 0 0 4px rgba(0, 0, 0, 0.15);
              padding: 5px 10px;
            }
          }
        }
        .editor-right-btns-box {
          position: absolute;
          top: 0;
          right: -54px;
          height: 45px;
          overflow: hidden;
          transition: all 0.4s;
          .editor-right-btns {
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
            .circle {
              width: 45px;
              height: 45px;
              border-bottom: 1px #fff solid;
              margin-left: 0;
              display: flex;
              justify-content: center;
              align-items: center;
              flex-direction: column;
              cursor: pointer;
              font-size: 14px;
              background: $mainColor;
              color: #fff;
              box-sizing: border-box;
              overflow: hidden;
              .el-icon,
              i {
                font-size: 24px;
              }
              &:first-child {
                border-top-left-radius: 5px;
                border-top-right-radius: 5px;
              }
              &:last-child {
                border-bottom-left-radius: 5px;
                border-bottom-right-radius: 5px;
              }
            }
          }
          &.active {
            height: calc(6 * 45px);
            .circle {
              &:first-child {
                border-top-left-radius: 5px;
                border-top-right-radius: 5px;
              }
              &:last-child {
                border-bottom-left-radius: 5px;
                border-bottom-right-radius: 5px;
              }
            }
          }
        }
      }
    }
    .publish-expand {
      width: 0;
      background-color: $white;
      position: relative;
      transition: all 0.8s;
      height: 100%;
      z-index: 8;
      &.col-expand {
        width: 430px;
        box-shadow: -5px 0 10px rgba(0, 0, 0, 0.1);
        .col-btn i {
          transform: rotate(0deg);
        }
      }
      .col-btn {
        position: absolute;
        height: 120px;
        width: 16px;
        left: -16px;
        top: 50%;
        transform: translateY(-50%);
        border-top-left-radius: 4px;
        border-bottom-left-radius: 4px;
        background-color: $mainColor;
        display: flex;
        justify-content: center;
        align-items: center;
        cursor: pointer;
        i {
          color: #fff;
          font-size: 12px;
          transform: rotate(180deg);
        }
      }
      .inner-expand-content {
        width: 430px;
        box-sizing: border-box;
        padding: 0 30px;
        .basic-attribute {
          display: flex;
          height: calc(100vh - 280px);
        }
        ::v-deep(.el-tabs__item) {
          height: 65px;
          line-height: 65px;
          .expand-tabs-label {
            padding: 5px;
          }
        }
        ::v-deep(.el-form-item__label) {
          width: 80px;
        }
        ::v-deep(.is-active) {
          span.expand-tabs-label.el-tooltip__trigger.el-tooltip__trigger {
            background: #ddd;
            border-radius: 3px;
          }
        }

        .send-setting {
          p {
            display: flex;
            align-items: center;
            justify-content: space-between;
            height: 54px;
            border-bottom: 1px solid #c4c9d5;
            font-size: 14px;
            color: #606266;
          }
          li.send-item {
            height: 40px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 0 10px;
            border-bottom: 1px solid #e4e4e4;
            span {
              color: #606266;
              font-size: 14px;
            }
          }
        }
      }
    }
  }
}

.inner-collect {
  .collect-title {
    margin-bottom: 10px;
  }
  .collect-tips {
    font-size: 14px;
    color: #aaaaaa;
  }
}

.publish-type-dialog {
  .publish-type-box {
    display: flex;
    justify-content: space-between;
    margin: 0 auto;
    width: 210px;
  }
}
</style>

<style lang="scss">
.publish-content {
  .toolbar {
    position: absolute;
    width: 100%;
    top: 0;
    left: 0;
    transition: all 0.4s;
    box-shadow: 0 0 10px rgba(#000, 0.1);
    z-index: 11;
    .tox-menubar,
    .tox-toolbar {
      background-image: none;
    }
    .tox-editor-header {
      border: none;
      margin: 0;
    }
    .tox-toolbar {
      flex-direction: column;
      justify-content: center;
      .tox-tbtn--bespoke {
        border: 1px solid $borderColor;
        .tox-tbtn__select-label {
          width: 6em;
        }
      }
      .tox-tbtn {
        height: auto;
        min-height: 34px;
        .image-group {
          padding: 7px 0;
          display: flex;
          flex-direction: column;
          justify-content: center;
          align-items: center;
          i {
            font-size: 40px;
          }
        }
        .image-group.link-group {
          i {
            font-size: 30px;
            margin: 5px 0;
          }
        }
      }
      .tox-tbtn--bespoke:not(:last-of-type) {
        margin-right: 10px;
      }
      .tox-toolbar__group:not(:last-of-type) {
        border-right: none;
      }
      .tox-toolbar__group {
        padding: 0 8px;
      }
    }
    .tox-toolbar:not(:last-of-type) {
      border-right: 1px solid $borderColor;
    }
    .tox-toolbar-overlord {
      display: flex;
      padding-bottom: 10px;
    }
  }
}
</style>
<style>
.el-popover.style-popover {
  padding: 5px;
  min-width: 80px;
  background: #303133;
}
.el-popover.style-popover .style-choose {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.el-popover.style-popover .el-popper__arrow::before {
  background: #303133;
}
</style>
